#include <string.h>
#include "sipsiparser.h"
#include "builderplugin.h"
#include "plugindvbfun.h"
#include "pluginbat.h"

#define MANUAL_SCAN_RECV_BAT_MAX	20

int PluginBatStartFilter(builder_bat_control_t* pstBatRecvCntrl)
{
	int s32Ret = -1;
	unsigned char au8Data[16];
	unsigned char au8Mask[16];

	PluginDvbLogcat("PluginBatStartFilter() - entry\r\n");
	memset(au8Data, 0, sizeof(au8Data));
	memset(au8Mask, 0, sizeof(au8Mask));
	au8Data[0] = SIPSI_TID_BAT;
	au8Mask[0] = 0xFF;
	au8Data[3] = 0x61;
	au8Mask[3] = 0xFF;
	au8Data[4] = 0x00;
	au8Mask[4] = 0xFF;
	s32Ret = PluginDvbSetFilter(&pstBatRecvCntrl->m_u32FilterID, SIPSI_PID_SDTBAT, au8Data, au8Mask, 5);
	if(s32Ret == 0)
	{
		PluginDvbLogcat("PluginBatStartFilter() - set filter OK\r\n");
	}
	else
	{
		PluginDvbLogcat("PluginBatStartFilter() - set filter error\r\n");
	}

	PluginDvbLogcat("PluginBatStartFilter() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}


int PluginBatStart(builder_bat_control_t* pstBatRecvCntrl)
{
	int s32Ret = -1;

	if(pstBatRecvCntrl)
	{
		s32Ret = PluginBatStartFilter(pstBatRecvCntrl);
		pstBatRecvCntrl->m_u32TimeOut = 10;
		pstBatRecvCntrl->m_u32SectionRecvCnt = 0;
		memset(pstBatRecvCntrl->m_au8SecRecvBitmap, 0, sizeof(pstBatRecvCntrl->m_au8SecRecvBitmap));
	}

	return s32Ret;
}

int PluginBatTick(builder_bat_control_t* pstBatRecvCntrl)
{
	int s32Ret = -1;

	if(pstBatRecvCntrl)
	{
		s32Ret = 0;
		pstBatRecvCntrl->m_u32TimeOut--;
		if(pstBatRecvCntrl->m_u32TimeOut == 0)
		{
			if(pstBatRecvCntrl->m_u32FilterID != BUILDER_INVALID_FILTER)
			{
				PluginDvbReleaseFilter(pstBatRecvCntrl->m_u32FilterID);
				pstBatRecvCntrl->m_u32FilterID = BUILDER_INVALID_FILTER;
			}
			pstBatRecvCntrl->m_u32Process = 100;
			if(pstBatRecvCntrl->m_pstBatSection)
			{
				PluginFreeTable(pstBatRecvCntrl->m_pstBatSection);
				pstBatRecvCntrl->m_pstBatSection = NULL;
			}
			s32Ret = -1;
		}
	}
	return s32Ret;
}


int PluginBatRecv(builder_bat_control_t* pstBatRecvCntrl, unsigned int hFilter, unsigned char* pu8Section)
{
	int s32Ret = -1;
	unsigned char u8SectionNum;
	unsigned char u8LastSectionNum;
	builder_section_t* pstSection;
	builder_section_t* pstTmpPrevSection;
	builder_section_t* pstTmpSection;
	unsigned int u32Len;
	unsigned int i;
	unsigned int u32SectionRecvCnt = 0;

	if(pstBatRecvCntrl && hFilter==pstBatRecvCntrl->m_u32FilterID)
	{
		s32Ret = 0;
		pstBatRecvCntrl->m_u32TimeOut = 10;
		pstBatRecvCntrl->m_u32SectionRecvCnt++;
		u8SectionNum = SiPsiGetSectionNo(pu8Section);
		u8LastSectionNum = SiPsiGetLastSectionNo(pu8Section);
		if(pstBatRecvCntrl->m_au8SecRecvBitmap[u8SectionNum] == 0)
		{
			u32Len = SiPsiGetSectionLength(pu8Section) + 3;
			pstSection = PluginDvbMemAlloc(sizeof(builder_section_t) + u32Len);
			if(pstSection)
			{
				memcpy(pstSection->m_au8Section, pu8Section, u32Len);
				pstTmpPrevSection = pstBatRecvCntrl->m_pstBatSection;
				if(pstTmpPrevSection && SiPsiGetSectionNo(pstTmpPrevSection->m_au8Section)<u8SectionNum)
				{
					pstTmpSection = pstTmpPrevSection->m_pstNext;
					while(pstTmpSection)
					{
						if(SiPsiGetSectionNo(pstTmpSection->m_au8Section)>u8SectionNum)
							break;
						pstTmpPrevSection = pstTmpSection;
						pstTmpSection = pstTmpPrevSection->m_pstNext;
					}
					pstSection->m_pstNext = pstTmpSection;
					pstTmpPrevSection->m_pstNext = pstSection;
				}
				else
				{
					pstSection->m_pstNext = pstBatRecvCntrl->m_pstBatSection;
					pstBatRecvCntrl->m_pstBatSection = pstSection;
				}
			}
			else
			{	
				PluginDvbLogcat("PluginBatRecv() -malloc section failed\r\n");
			}
			pstBatRecvCntrl->m_au8SecRecvBitmap[u8SectionNum] = 1;
		}

		for(i=0; i<=u8LastSectionNum; i++)
		{
			if(pstBatRecvCntrl->m_au8SecRecvBitmap[i] == 1)
			{
				u32SectionRecvCnt++;
			}
		}

		if(u32SectionRecvCnt > u8LastSectionNum)
		{
			PluginDvbReleaseFilter(pstBatRecvCntrl->m_u32FilterID);
			pstBatRecvCntrl->m_u32FilterID = BUILDER_INVALID_FILTER;
			pstBatRecvCntrl->m_u32Process = 100;
		}
		else if(pstBatRecvCntrl->m_u32SectionRecvCnt > MANUAL_SCAN_RECV_BAT_MAX)
		{
			PluginDvbLogcat("PluginBatRecv() -recv section time out\r\n");
			PluginDvbReleaseFilter(pstBatRecvCntrl->m_u32FilterID);
			pstBatRecvCntrl->m_u32FilterID = BUILDER_INVALID_FILTER;
			pstTmpSection = pstBatRecvCntrl->m_pstBatSection;
			do
			{
				pstSection = pstTmpSection;
				pstTmpSection = pstSection->m_pstNext;
				PluginDvbMemFree(pstSection);
			}while(pstTmpSection);
			pstBatRecvCntrl->m_pstBatSection = NULL;
			pstBatRecvCntrl->m_u32Process = 100;
			s32Ret = -1;		
		}
		else
		{
			pstBatRecvCntrl->m_u32Process = u32SectionRecvCnt*100/(u8LastSectionNum+1);
		}
	}

	return s32Ret;
}

int PluginBatGetProcess(builder_bat_control_t* pstBatRecvCntrl, unsigned int* pu32Process)
{
	int s32Ret = -1; 

	if(pstBatRecvCntrl)
	{
		*pu32Process = pstBatRecvCntrl->m_u32Process;
		s32Ret = 0;
	}

	return s32Ret;
}

int PluginBatStop(builder_bat_control_t* pstBatRecvCntrl)
{
	int s32Ret;
	
	s32Ret = PluginBatReset(pstBatRecvCntrl);

	return s32Ret;
}

int PluginBatReset(builder_bat_control_t* pstBatRecvCntrl)
{
	int s32Ret = -1;

	if(pstBatRecvCntrl)
	{
		s32Ret = -1;
		pstBatRecvCntrl->m_u32TimeOut = 0;
		if(pstBatRecvCntrl->m_u32FilterID != BUILDER_INVALID_FILTER)
		{
			PluginDvbReleaseFilter(pstBatRecvCntrl->m_u32FilterID);
			pstBatRecvCntrl->m_u32FilterID = BUILDER_INVALID_FILTER;
		}

		if(pstBatRecvCntrl->m_pstBatSection)
		{
			PluginFreeTable(pstBatRecvCntrl->m_pstBatSection);
			pstBatRecvCntrl->m_pstBatSection = NULL;
		}

		memset(pstBatRecvCntrl->m_au8SecRecvBitmap, 0, sizeof(pstBatRecvCntrl->m_au8SecRecvBitmap));
		pstBatRecvCntrl->m_u32SectionRecvCnt = 0;

		pstBatRecvCntrl->m_u32Process = 0;
	}

	return s32Ret;
}

int PluginBatGetSections(builder_bat_control_t* pstBatRecvCntrl, builder_section_t** ppstBat)
{
	int s32Ret = -1;
	
	if(pstBatRecvCntrl)
	{
		*ppstBat = pstBatRecvCntrl->m_pstBatSection;
		pstBatRecvCntrl->m_pstBatSection = NULL;
	}

	return s32Ret;
}

